home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / ghostview-1.5 / Draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  16.5 KB  |  921 lines

  1. /*
  2.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Software Research Associates not be used
  9.  * in advertising or publicity pertaining to distribution of the software
  10.  * without specific, written prior permission.  Software Research Associates
  11.  * makes no representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  16.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  18.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author: Erik M. van der Poel
  23.  *         Software Research Associates, Inc., Tokyo, Japan
  24.  *         erik@sra.co.jp
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include "SFinternal.h"
  29. #include "xstat.h"
  30. #include <X11/StringDefs.h>
  31. #include <X11/Xaw/Scrollbar.h>
  32. #include <X11/Xaw/Cardinals.h>
  33.  
  34. #define SF_DEFAULT_FONT "9x15"
  35.  
  36. #ifdef ABS
  37. #undef ABS
  38. #endif
  39. #define ABS(x) (((x) < 0) ? (-(x)) : (x))
  40.  
  41. typedef struct {
  42.     char *fontname;
  43. } TextData, *textPtr;
  44.  
  45. int SFcharWidth, SFcharAscent, SFcharHeight;
  46.  
  47. int SFcurrentInvert[3] = { -1, -1, -1 };
  48.  
  49. static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
  50.  
  51. static XtResource textResources[] = {
  52.     {XtNfont, XtCFont, XtRString, sizeof (char *),
  53.         XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
  54. };
  55.  
  56. static XFontStruct *SFfont;
  57.  
  58. static int SFcurrentListY;
  59.  
  60. static XtIntervalId SFscrollTimerId;
  61.  
  62. SFinitFont()
  63. {
  64.     TextData    *data;
  65.  
  66.     data = XtNew(TextData);
  67.  
  68.     XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
  69.         XtNumber(textResources), (Arg *) NULL, ZERO);
  70.  
  71.     SFfont = XLoadQueryFont(SFdisplay, data->fontname);
  72.     if (!SFfont) {
  73.         SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
  74.         if (!SFfont) {
  75.             char    sbuf[256];
  76.  
  77.             (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
  78.                 SF_DEFAULT_FONT);
  79.  
  80.             XtAppError(SFapp, sbuf);
  81.         }
  82.     }
  83.  
  84.     SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
  85.     SFcharAscent = SFfont->max_bounds.ascent;
  86.     SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
  87. }
  88.  
  89. SFcreateGC()
  90. {
  91.     XGCValues    gcValues;
  92.     XRectangle    rectangles[1];
  93.  
  94.     gcValues.foreground = SFfore;
  95.  
  96.     SFlineGC = XtGetGC(
  97.         selFileLists[0],
  98.         (XtGCMask)
  99.             GCForeground        |
  100.             0,
  101.         &gcValues
  102.     );
  103.  
  104.     SFscrollGC = XtGetGC(
  105.         selFileLists[0],
  106.         (XtGCMask)
  107.             0,
  108.         &gcValues
  109.     );
  110.  
  111.     gcValues.function = GXinvert;
  112.     gcValues.plane_mask = (SFfore ^ SFback);
  113.  
  114.     SFinvertGC = XtGetGC(
  115.         selFileLists[0],
  116.         (XtGCMask)
  117.             GCFunction        |
  118.             GCPlaneMask        |
  119.             0,
  120.         &gcValues
  121.     );
  122.  
  123.     gcValues.foreground = SFfore;
  124.     gcValues.background = SFback;
  125.     gcValues.font = SFfont->fid;
  126.  
  127.     SFtextGC = XCreateGC(
  128.         SFdisplay,
  129.         XtWindow(selFileLists[0]),
  130.         (unsigned long)
  131.             GCForeground        |
  132.             GCBackground        |
  133.             GCFont            |
  134.             0,
  135.         &gcValues
  136.     );
  137.  
  138.     rectangles[0].x = SFlineToTextH + SFbesideText;
  139.     rectangles[0].y = 0;
  140.     rectangles[0].width = SFcharsPerEntry * SFcharWidth;
  141.     rectangles[0].height = SFupperY + 1;
  142.  
  143.     XSetClipRectangles(
  144.         SFdisplay,
  145.         SFtextGC,
  146.         0,
  147.         0,
  148.         rectangles,
  149.         1,
  150.         Unsorted
  151.     );
  152. }
  153.  
  154. SFclearList(n, doScroll)
  155.     int    n;
  156.     int    doScroll;
  157. {
  158.     SFDir    *dir;
  159.  
  160.     SFcurrentInvert[n] = -1;
  161.  
  162.     XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
  163.  
  164.     XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
  165.         2);
  166.  
  167.     if (doScroll) {
  168.         dir = &(SFdirs[SFdirPtr + n]);
  169.  
  170.         if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
  171.             XawScrollbarSetThumb(
  172.                 selFileVScrolls[n],
  173.                 (float) (((double) dir->vOrigin) /
  174.                     dir->nEntries),
  175.                 (float) (((double) ((dir->nEntries < SFlistSize)
  176.                     ? dir->nEntries : SFlistSize)) /
  177.                     dir->nEntries)
  178.             );
  179.  
  180.             XawScrollbarSetThumb(
  181.                 selFileHScrolls[n],
  182.                 (float) (((double) dir->hOrigin) / dir->nChars),
  183.                 (float) (((double) ((dir->nChars <
  184.                     SFcharsPerEntry) ? dir->nChars :
  185.                     SFcharsPerEntry)) / dir->nChars)
  186.             );
  187.         } else {
  188.             XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
  189.                 (float) 1.0);
  190.             XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
  191.                 (float) 1.0);
  192.         }
  193.     }
  194. }
  195.  
  196. static
  197. SFdeleteEntry(dir, entry)
  198.     SFDir    *dir;
  199.     SFEntry    *entry;
  200. {
  201.     register SFEntry    *e;
  202.     register SFEntry    *end;
  203.     int            n;
  204.     int            idx;
  205.  
  206.     idx = entry - dir->entries;
  207.  
  208.     if (idx < dir->beginSelection) {
  209.         dir->beginSelection--;
  210.     }
  211.     if (idx <= dir->endSelection) {
  212.         dir->endSelection--;
  213.     }
  214.     if (dir->beginSelection > dir->endSelection) {
  215.         dir->beginSelection = dir->endSelection = -1;
  216.     }
  217.  
  218.     if (idx < dir->vOrigin) {
  219.         dir->vOrigin--;
  220.     }
  221.  
  222.     XtFree(entry->real);
  223.  
  224.     end = &(dir->entries[dir->nEntries - 1]);
  225.  
  226.     for (e = entry; e < end; e++) {
  227.         *e = *(e + 1);
  228.     }
  229.  
  230.     if (!(--dir->nEntries)) {
  231.         return;
  232.     }
  233.  
  234.     n = dir - &(SFdirs[SFdirPtr]);
  235.     if ((n < 0) || (n > 2)) {
  236.         return;
  237.     }
  238.  
  239.     XawScrollbarSetThumb(
  240.         selFileVScrolls[n],
  241.         (float) (((double) dir->vOrigin) / dir->nEntries),
  242.         (float) (((double) ((dir->nEntries < SFlistSize) ?
  243.             dir->nEntries : SFlistSize)) / dir->nEntries)
  244.     );
  245. }
  246.  
  247. static
  248. SFwriteStatChar(name, last, statBuf)
  249.     char        *name;
  250.     int        last;
  251.     struct stat    *statBuf;
  252. {
  253.     name[last] = SFstatChar(statBuf);
  254. }
  255.  
  256. static int
  257. SFstatAndCheck(dir, entry)
  258.     SFDir    *dir;
  259.     SFEntry    *entry;
  260. {
  261.     struct stat    statBuf;
  262.     char        save;
  263.     int        last;
  264.  
  265.     /*
  266.      * must be restored before returning
  267.      */
  268.     save = *(dir->path);
  269.     *(dir->path) = 0;
  270.  
  271.     if (!SFchdir(SFcurrentPath)) {
  272.         last = strlen(entry->real) - 1;
  273.         entry->real[last] = 0;
  274.         entry->statDone = 1;
  275.         if (
  276.             (!stat(entry->real, &statBuf))
  277.  
  278. #ifdef S_IFLNK
  279.  
  280.              || (!lstat(entry->real, &statBuf))
  281.  
  282. #endif /* ndef S_IFLNK */
  283.  
  284.         ) {
  285.             if (SFfunc) {
  286.                 char *shown;
  287.  
  288.                 shown = NULL;
  289.                 if (SFfunc(entry->real, &shown, &statBuf)) {
  290.                     if (shown) {
  291.                         int len;
  292.  
  293.                         len = strlen(shown);
  294.                         entry->shown = XtMalloc(
  295.                             (unsigned) (len + 2)
  296.                         );
  297.                         (void) strcpy(entry->shown,
  298.                             shown);
  299.                         SFwriteStatChar(
  300.                             entry->shown,
  301.                             len,
  302.                             &statBuf
  303.                         );
  304.                         entry->shown[len + 1] = 0;
  305.                     }
  306.                 } else {
  307.                     SFdeleteEntry(dir, entry);
  308.  
  309.                     *(dir->path) = save;
  310.                     return 1;
  311.                 }
  312.             }
  313.             SFwriteStatChar(entry->real, last, &statBuf);
  314.         } else {
  315.             entry->real[last] = ' ';
  316.         }
  317.     }
  318.  
  319.     *(dir->path) = save;
  320.     return 0;
  321. }
  322.  
  323. static
  324. SFdrawStrings(w, dir, from, to)
  325.     register Window    w;
  326.     register SFDir    *dir;
  327.     register int    from;
  328.     register int    to;
  329. {
  330.     register int        i;
  331.     register SFEntry    *entry;
  332.     int            x;
  333.  
  334.     x = SFtextX - dir->hOrigin * SFcharWidth;
  335.  
  336.     if (dir->vOrigin + to >= dir->nEntries) {
  337.         to = dir->nEntries - dir->vOrigin - 1;
  338.     }
  339.     for (i = from; i <= to; i++) {
  340.         entry = &(dir->entries[dir->vOrigin + i]);
  341.         if (!(entry->statDone)) {
  342.             if (SFstatAndCheck(dir, entry)) {
  343.                 if (dir->vOrigin + to >= dir->nEntries) {
  344.                     to = dir->nEntries - dir->vOrigin - 1;
  345.                 }
  346.                 i--;
  347.                 continue;
  348.             }
  349.         }
  350.         XDrawImageString(
  351.             SFdisplay,
  352.             w,
  353.             SFtextGC,
  354.             x,
  355.             SFtextYoffset + i * SFentryHeight,
  356.             entry->shown,
  357.             strlen(entry->shown)
  358.         );
  359.         if (dir->vOrigin + i == dir->beginSelection) {
  360.             XDrawLine(
  361.                 SFdisplay,
  362.                 w,
  363.                 SFlineGC,
  364.                 SFlineToTextH + 1,
  365.                 SFlowerY + i * SFentryHeight,
  366.                 SFlineToTextH + SFentryWidth - 2,
  367.                 SFlowerY + i * SFentryHeight
  368.             );
  369.         }
  370.         if (
  371.             (dir->vOrigin + i >= dir->beginSelection) &&
  372.             (dir->vOrigin + i <= dir->endSelection)
  373.         ) {
  374.             SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
  375.                 SFlowerY + i * SFentryHeight;
  376.             SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
  377.                 SFlowerY + (i + 1) * SFentryHeight - 1;
  378.             XDrawSegments(
  379.                 SFdisplay,
  380.                 w,
  381.                 SFlineGC,
  382.                 SFcompletionSegs,
  383.                 2
  384.             );
  385.         }
  386.         if (dir->vOrigin + i == dir->endSelection) {
  387.             XDrawLine(
  388.                 SFdisplay,
  389.                 w,
  390.                 SFlineGC,
  391.                 SFlineToTextH + 1,
  392.                 SFlowerY + (i + 1) * SFentryHeight - 1,
  393.                 SFlineToTextH + SFentryWidth - 2,
  394.                 SFlowerY + (i + 1) * SFentryHeight - 1
  395.             );
  396.         }
  397.     }
  398. }
  399.  
  400. SFdrawList(n, doScroll)
  401.     int    n;
  402.     int    doScroll;
  403. {
  404.     SFDir    *dir;
  405.     Window    w;
  406.  
  407.     SFclearList(n, doScroll);
  408.  
  409.     if (SFdirPtr + n < SFdirEnd) {
  410.         dir = &(SFdirs[SFdirPtr + n]);
  411.         w = XtWindow(selFileLists[n]);
  412.         XDrawImageString(
  413.             SFdisplay,
  414.             w,
  415.             SFtextGC,
  416.             SFtextX - dir->hOrigin * SFcharWidth,
  417.             SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
  418.             dir->dir,
  419.             strlen(dir->dir)
  420.         );
  421.         SFdrawStrings(w, dir, 0, SFlistSize - 1);
  422.     }
  423. }
  424.  
  425. SFdrawLists(doScroll)
  426.     int    doScroll;
  427. {
  428.     int    i;
  429.  
  430.     for (i = 0; i < 3; i++) {
  431.         SFdrawList(i, doScroll);
  432.     }
  433. }
  434.  
  435. static
  436. SFinvertEntry(n)
  437.     register int    n;
  438. {
  439.     XFillRectangle(
  440.         SFdisplay,
  441.         XtWindow(selFileLists[n]),
  442.         SFinvertGC,
  443.         SFlineToTextH,
  444.         SFcurrentInvert[n] * SFentryHeight + SFlowerY,
  445.         SFentryWidth,
  446.         SFentryHeight
  447.     );
  448. }
  449.  
  450. static unsigned long
  451. SFscrollTimerInterval()
  452. {
  453.     static int    maxVal = 200;
  454.     static int    varyDist = 50;
  455.     static int    minDist = 50;
  456.     int        t;
  457.     int        dist;
  458.  
  459.     if (SFcurrentListY < SFlowerY) {
  460.         dist = SFlowerY - SFcurrentListY;
  461.     } else if (SFcurrentListY > SFupperY) {
  462.         dist = SFcurrentListY - SFupperY;
  463.     } else {
  464.         return (unsigned long) 1;
  465.     }
  466.  
  467.     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
  468.  
  469.     if (t < 1) {
  470.         t = 1;
  471.     }
  472.  
  473.     if (t > maxVal) {
  474.         t = maxVal;
  475.     }
  476.  
  477.     return (unsigned long) t;
  478. }
  479.  
  480. static void
  481. SFscrollTimer(p, id)
  482.     XtPointer    p;
  483.         XtIntervalId    *id;
  484. {
  485.     SFDir    *dir;
  486.     int    save;
  487.     int     n;
  488.  
  489.         n = (int) p;
  490.  
  491.     dir = &(SFdirs[SFdirPtr + n]);
  492.     save = dir->vOrigin;
  493.  
  494.     if (SFcurrentListY < SFlowerY) {
  495.         if (dir->vOrigin > 0) {
  496.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  497.                 dir->vOrigin - 1);
  498.         }
  499.     } else if (SFcurrentListY > SFupperY) {
  500.         if (dir->vOrigin < dir->nEntries - SFlistSize) {
  501.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  502.                 dir->vOrigin + 1);
  503.         }
  504.     }
  505.  
  506.     if (dir->vOrigin != save) {
  507.         if (dir->nEntries) {
  508.             XawScrollbarSetThumb(
  509.             selFileVScrolls[n],
  510.             (float) (((double) dir->vOrigin) / dir->nEntries),
  511.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  512.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  513.             );
  514.         }
  515.     }
  516.  
  517.     if (SFbuttonPressed) {
  518.         SFscrollTimerId = XtAppAddTimeOut(SFapp,
  519.             SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
  520.     }
  521. }
  522.  
  523. static int
  524. SFnewInvertEntry(n, event)
  525.     register int        n;
  526.     register XMotionEvent    *event;
  527. {
  528.     register int    x, y;
  529.     register int    new;
  530.     static int    SFscrollTimerAdded = 0;
  531.  
  532.     x = event->x;
  533.     y = event->y;
  534.  
  535.     if (SFdirPtr + n >= SFdirEnd) {
  536.         return -1;
  537.     } else if (
  538.         (x >= 0)    && (x <= SFupperX) &&
  539.         (y >= SFlowerY)    && (y <= SFupperY)
  540.     ) {
  541.         register SFDir *dir = &(SFdirs[SFdirPtr + n]);
  542.  
  543.         if (SFscrollTimerAdded) {
  544.             SFscrollTimerAdded = 0;
  545.             XtRemoveTimeOut(SFscrollTimerId);
  546.         }
  547.  
  548.         new = (y - SFlowerY) / SFentryHeight;
  549.         if (dir->vOrigin + new >= dir->nEntries) {
  550.             return -1;
  551.         }
  552.         return new;
  553.     } else {
  554.         if (SFbuttonPressed) {
  555.             SFcurrentListY = y;
  556.             if (!SFscrollTimerAdded) {
  557.                 SFscrollTimerAdded = 1;
  558.                 SFscrollTimerId = XtAppAddTimeOut(SFapp,
  559.                     SFscrollTimerInterval(), SFscrollTimer,
  560.                     (XtPointer) n);
  561.             }
  562.         }
  563.  
  564.         return -1;
  565.     }
  566. }
  567.  
  568. /* ARGSUSED */
  569. void
  570. SFenterList(w, n, event)
  571.     Widget                w;
  572.     register int            n;
  573.     register XEnterWindowEvent    *event;
  574. {
  575.     register int    new;
  576.  
  577.     /* sanity */
  578.     if (SFcurrentInvert[n] != -1) {
  579.         SFinvertEntry(n);
  580.         SFcurrentInvert[n] = -1;
  581.     }
  582.  
  583.     new = SFnewInvertEntry(n, (XMotionEvent *) event);
  584.     if (new != -1) {
  585.         SFcurrentInvert[n] = new;
  586.         SFinvertEntry(n);
  587.     }
  588. }
  589.  
  590. /* ARGSUSED */
  591. void
  592. SFleaveList(w, n, event)
  593.     Widget        w;
  594.     register int    n;
  595.     XEvent        *event;
  596. {
  597.     if (SFcurrentInvert[n] != -1) {
  598.         SFinvertEntry(n);
  599.         SFcurrentInvert[n] = -1;
  600.     }
  601. }
  602.  
  603. /* ARGSUSED */
  604. void
  605. SFmotionList(w, n, event)
  606.     Widget            w;
  607.     register int        n;
  608.     register XMotionEvent    *event;
  609. {
  610.     register int    new;
  611.  
  612.     new = SFnewInvertEntry(n, event);
  613.  
  614.     if (new != SFcurrentInvert[n]) {
  615.         if (SFcurrentInvert[n] != -1) {
  616.             SFinvertEntry(n);
  617.         }
  618.         SFcurrentInvert[n] = new;
  619.         if (new != -1) {
  620.             SFinvertEntry(n);
  621.         }
  622.     }
  623. }
  624.  
  625. /* ARGSUSED */
  626. void
  627. SFvFloatSliderMovedCallback(w, n, fnew)
  628.     Widget    w;
  629.     int    n;
  630.     float    *fnew;
  631. {
  632.     int    new;
  633.  
  634.     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
  635.  
  636.     SFvSliderMovedCallback(w, n, new);
  637. }
  638.  
  639. /* ARGSUSED */
  640. void
  641. SFvSliderMovedCallback(w, n, new)
  642.     Widget    w;
  643.     int    n;
  644.     int    new;
  645. {
  646.     int        old;
  647.     register Window    win;
  648.     SFDir        *dir;
  649.  
  650.     dir = &(SFdirs[SFdirPtr + n]);
  651.  
  652.     old = dir->vOrigin;
  653.     dir->vOrigin = new;
  654.  
  655.     if (old == new) {
  656.         return;
  657.     }
  658.  
  659.     win = XtWindow(selFileLists[n]);
  660.  
  661.     if (ABS(new - old) < SFlistSize) {
  662.         if (new > old) {
  663.             XCopyArea(
  664.                 SFdisplay,
  665.                 win,
  666.                 win,
  667.                 SFscrollGC,
  668.                 SFlineToTextH,
  669.                 SFlowerY + (new - old) * SFentryHeight,
  670.                 SFentryWidth + SFlineToTextH,
  671.                 (SFlistSize - (new - old)) * SFentryHeight,
  672.                 SFlineToTextH,
  673.                 SFlowerY
  674.             );
  675.             XClearArea(
  676.                 SFdisplay,
  677.                 win,
  678.                 SFlineToTextH,
  679.                 SFlowerY + (SFlistSize - (new - old)) *
  680.                     SFentryHeight,
  681.                 SFentryWidth + SFlineToTextH,
  682.                 (new - old) * SFentryHeight,
  683.                 False
  684.             );
  685.             SFdrawStrings(win, dir, SFlistSize - (new - old),
  686.                 SFlistSize - 1);
  687.         } else {
  688.             XCopyArea(
  689.                 SFdisplay,
  690.                 win,
  691.                 win,
  692.                 SFscrollGC,
  693.                 SFlineToTextH,
  694.                 SFlowerY,
  695.                 SFentryWidth + SFlineToTextH,
  696.                 (SFlistSize - (old - new)) * SFentryHeight,
  697.                 SFlineToTextH,
  698.                 SFlowerY + (old - new) * SFentryHeight
  699.             );
  700.             XClearArea(
  701.                 SFdisplay,
  702.                 win,
  703.                 SFlineToTextH,
  704.                 SFlowerY,
  705.                 SFentryWidth + SFlineToTextH,
  706.                 (old - new) * SFentryHeight,
  707.                 False
  708.             );
  709.             SFdrawStrings(win, dir, 0, old - new);
  710.         }
  711.     } else {
  712.         XClearArea(
  713.             SFdisplay,
  714.             win,
  715.             SFlineToTextH,
  716.             SFlowerY,
  717.             SFentryWidth + SFlineToTextH,
  718.             SFlistSize * SFentryHeight,
  719.             False
  720.         );
  721.         SFdrawStrings(win, dir, 0, SFlistSize - 1);
  722.     }
  723. }
  724.  
  725. /* ARGSUSED */
  726. void
  727. SFvAreaSelectedCallback(w, n, pnew)
  728.     Widget    w;
  729.     int    n;
  730.     int    pnew;
  731. {
  732.     SFDir    *dir;
  733.     int    new;
  734.  
  735.     dir = &(SFdirs[SFdirPtr + n]);
  736.  
  737.     new = dir->vOrigin +
  738.         (((double) pnew) / SFvScrollHeight) * dir->nEntries;
  739.  
  740.     if (new > dir->nEntries - SFlistSize) {
  741.         new = dir->nEntries - SFlistSize;
  742.     }
  743.  
  744.     if (new < 0) {
  745.         new = 0;
  746.     }
  747.  
  748.     if (dir->nEntries) {
  749.         float    f;
  750.  
  751.         f = ((double) new) / dir->nEntries;
  752.  
  753.         XawScrollbarSetThumb(
  754.             w,
  755.             f,
  756.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  757.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  758.         );
  759.     }
  760.  
  761.     SFvSliderMovedCallback(w, n, new);
  762. }
  763.  
  764. /* ARGSUSED */
  765. void
  766. SFhSliderMovedCallback(w, n, new)
  767.     Widget    w;
  768.     int    n;
  769.     float    *new;
  770. {
  771.     SFDir    *dir;
  772.     int    save;
  773.  
  774.     dir = &(SFdirs[SFdirPtr + n]);
  775.     save = dir->hOrigin;
  776.     dir->hOrigin = (*new) * dir->nChars;
  777.     if (dir->hOrigin == save) {
  778.         return;
  779.     }
  780.  
  781.     SFdrawList(n, SF_DO_NOT_SCROLL);
  782. }
  783.  
  784. /* ARGSUSED */
  785. void
  786. SFhAreaSelectedCallback(w, n, pnew)
  787.     Widget    w;
  788.     int    n;
  789.     int    pnew;
  790. {
  791.     SFDir    *dir;
  792.     int    new;
  793.  
  794.     dir = &(SFdirs[SFdirPtr + n]);
  795.  
  796.     new = dir->hOrigin +
  797.         (((double) pnew) / SFhScrollWidth) * dir->nChars;
  798.  
  799.     if (new > dir->nChars - SFcharsPerEntry) {
  800.         new = dir->nChars - SFcharsPerEntry;
  801.     }
  802.  
  803.     if (new < 0) {
  804.         new = 0;
  805.     }
  806.  
  807.     if (dir->nChars) {
  808.         float    f;
  809.  
  810.         f = ((double) new) / dir->nChars;
  811.  
  812.         XawScrollbarSetThumb(
  813.             w,
  814.             f,
  815.             (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
  816.                 dir->nChars : SFcharsPerEntry)) / dir->nChars)
  817.         );
  818.  
  819.         SFhSliderMovedCallback(w, n, &f);
  820.     }
  821. }
  822.  
  823. /* ARGSUSED */
  824. void
  825. SFpathSliderMovedCallback(w, client_data, new)
  826.     Widget        w;
  827.     XtPointer    client_data;
  828.     float    *new;
  829. {
  830.     SFDir        *dir;
  831.     int        n;
  832.     XawTextPosition    pos;
  833.     int    SFdirPtrSave;
  834.  
  835.     SFdirPtrSave = SFdirPtr;
  836.     SFdirPtr = (*new) * SFdirEnd;
  837.     if (SFdirPtr == SFdirPtrSave) {
  838.         return;
  839.     }
  840.  
  841.     SFdrawLists(SF_DO_SCROLL);
  842.  
  843.     n = 2;
  844.     while (SFdirPtr + n >= SFdirEnd) {
  845.         n--;
  846.     }
  847.  
  848.     dir = &(SFdirs[SFdirPtr + n]);
  849.  
  850.     pos = dir->path - SFcurrentPath;
  851.  
  852.     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  853.         pos -= strlen(SFstartDir);
  854.         if (pos < 0) {
  855.             pos = 0;
  856.         }
  857.     }
  858.  
  859.     XawTextSetInsertionPoint(selFileField, pos);
  860. }
  861.  
  862. /* ARGSUSED */
  863.  
  864. void
  865. SFpathAreaSelectedCallback(w, client_data, pnew)
  866.     Widget        w;
  867.     XtPointer    client_data;
  868.     int        pnew;
  869. {
  870.     int    new;
  871.     float    f;
  872.  
  873.     new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
  874.  
  875.     if (new > SFdirEnd - 3) {
  876.         new = SFdirEnd - 3;
  877.     }
  878.  
  879.     if (new < 0) {
  880.         new = 0;
  881.     }
  882.  
  883.     f = ((double) new) / SFdirEnd;
  884.  
  885.     XawScrollbarSetThumb(
  886.         w,
  887.         f,
  888.         (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  889.             SFdirEnd)
  890.     );
  891.  
  892.     SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
  893. }
  894.  
  895. Boolean
  896. SFworkProc()
  897. {
  898.     register SFDir        *dir;
  899.     register SFEntry    *entry;
  900.  
  901.     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  902.         if (!(dir->nEntries)) {
  903.             continue;
  904.         }
  905.         for (
  906.             entry = &(dir->entries[dir->nEntries - 1]);
  907.             entry >= dir->entries;
  908.             entry--
  909.         ) {
  910.             if (!(entry->statDone)) {
  911.                 (void) SFstatAndCheck(dir, entry);
  912.                 return False;
  913.             }
  914.         }
  915.     }
  916.  
  917.     SFworkProcAdded = 0;
  918.  
  919.     return True;
  920. }
  921.